﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Text.RegularExpressions;

namespace JSFileCom
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog dlg = new FolderBrowserDialog();
            dlg.SelectedPath = txtdir.Text;
            dlg.ShowDialog();
            txtdir.Text = dlg.SelectedPath;
        }

        private void button2_Click(object sender, EventArgs e)
        {
            StringBuilder str = new StringBuilder();
            make(str, txtdir.Text);
            File.WriteAllText(txtout.Text, str.ToString(), Encoding.UTF8);
            MessageBox.Show("ok!");
        }

        void make(StringBuilder str, string path)
        {
            var dir = new DirectoryInfo(path);
            foreach (var file in dir.GetFiles(txttype.Text))
            {
                StreamReader sr = new StreamReader(file.FullName);
                var enco = sr.CurrentEncoding;
                sr.Close();
                str.AppendLine(File.ReadAllText(file.FullName, enco));
            }
            foreach (var subdir in dir.GetDirectories())
                make(str, subdir.FullName);
        }

        private void button3_Click(object sender, EventArgs e)
        {
            var dlg = new SaveFileDialog();
            dlg.ShowDialog();
            txtout.Text = dlg.FileName;
        }

        private void button4_Click(object sender, EventArgs e)
        {
            toutf(txtdir.Text);
            MessageBox.Show("ok!");
        }

        void toutf(string path)
        {
            var dir = new DirectoryInfo(path);
            foreach (var file in dir.GetFiles(txttype.Text, SearchOption.AllDirectories))
            {
                StreamReader sr = new StreamReader(file.FullName);
                var encode = sr.CurrentEncoding;
                sr.Close();
                if (encode == Encoding.UTF8) continue;
                file.CopyTo(file.FullName + ".bak");
                File.WriteAllText(file.FullName, File.ReadAllText(file.FullName, encode), Encoding.UTF8);
            }
        }

        private void button5_Click(object sender, EventArgs e)
        {
            File.Delete(txtout.Text);
            var dir = new DirectoryInfo(txtdir.Text);
            var ns = new HashSet<string>();
            var func = new HashSet<string>();
            var str = new StringBuilder();
            foreach (var file in dir.GetFiles(txttype.Text, SearchOption.AllDirectories))
            {
                var txt = File.ReadAllText(file.FullName, Encoding.UTF8);
                var matchs = Regex.Matches(txt, @"Ext\.(ns|namespace)\(['""](?<name>[^'""]+)['""]\)");
                foreach (Match m in matchs) ns.Add(m.Groups["name"].Value);
                matchs = Regex.Matches(txt, @" on[cC]lick=""(?<name>\w+)\(");
                foreach (Match m in matchs) func.Add(m.Groups["name"].Value);
                txt = Regex.Replace(txt, @"Ext\.(ns|namespace)\(['""][^'""]+['""]\);?\n?", "");
                txt = Regex.Replace(txt, @" on[cC]lick=""(\w+)\(", @" onclick=""'+_$1+'(");
                str.AppendLine(txt);
            }
            foreach (var name in func)
                str.Insert(0, string.Format("var _{0}=getFuncName({0});\r\n", name));

            var nsdic = new SortedDictionary<string, object>();
            foreach (var name in ns)
            {
                var subnames = name.Split('.');
                var dic = nsdic;
                for (var i = 0; i < subnames.Length; ++i)
                {
                    var subname = subnames[i].Trim();
                    if (dic.ContainsKey(subname))
                        dic = (SortedDictionary<string, object>)dic[subname];
                    else
                    {
                        var newdic = new SortedDictionary<string, object>();
                        dic.Add(subname, newdic);
                        dic = newdic;
                    }
                }
            }

            var q = new Queue<KeyValuePair<string, object>>();
            var tmpstr = new StringBuilder();
            foreach (var name in nsdic)
            {
                if (name.Key == "Ext")
                    tmpstr.Append("var Ext=theExt;\r\n");
                else
                    tmpstr.AppendFormat("var {0}={{}};\r\n", name.Key);
                q.Enqueue(name);
            }
            while (q.Count != 0)
            {
                var pair = q.Dequeue();
                foreach (var name in (SortedDictionary<string, object>)pair.Value)
                {
                    tmpstr.AppendFormat("{0}.{1}={{}};\r\n", pair.Key, name.Key);
                    q.Enqueue(new KeyValuePair<string, object>(pair.Key + "." + name.Key, name.Value));
                }
            }

            str.Insert(0, tmpstr.ToString());
            str.Insert(0, "(function(){\r\n");
            str.AppendLine("})();");
            File.WriteAllText(txtout.Text, str.ToString(), Encoding.UTF8);
            MessageBox.Show("ok!");
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            txtdir.Text = Application.StartupPath;
            //txtout.Text = txtdir.Text + "\\oj.js";
        }

        private void button6_Click(object sender, EventArgs e)
        {
            string str = File.ReadAllText(txtout.Text, Encoding.UTF8);
            var start = str.IndexOf("(function (){");
            if (start == -1)
            {
                MessageBox.Show("not found");
                return;
            }
            str = "(function(){" + str.Remove(start, 13);
            File.WriteAllText(txtout.Text, str, Encoding.UTF8);
            MessageBox.Show("ok");
        }

        private void button7_Click(object sender, EventArgs e)
        {
            string str = File.ReadAllText(txtout.Text, Encoding.UTF8);
            str = str.Trim(' ', '\t', '\r', '\n', '　');
            if (str.StartsWith("(function(){"))
                str = str.Substring(12);
            if (str.EndsWith("})();"))
                str = str.Substring(0, str.Length - 5);
            str = str.Trim(' ', '\t', '\r', '\n', '　');
            str = str.Replace("theExt", "Ext");
            File.WriteAllText(txtout.Text, str, Encoding.UTF8);
            MessageBox.Show("ok");
        }

        private void Form1_DragDrop(object sender, DragEventArgs e)
        {
            if (!e.Data.GetDataPresent(DataFormats.FileDrop, false)) return;
            string filename = ((string[])e.Data.GetData(DataFormats.FileDrop))[0];
            txtout.Text = filename;
        }

        private void Form1_DragEnter(object sender, DragEventArgs e)
        {
            e.Effect = DragDropEffects.All;
        }

        private void Form1_DragOver(object sender, DragEventArgs e)
        {
            e.Effect = DragDropEffects.All;
        }

        private void txttype_SelectedIndexChanged(object sender, EventArgs e)
        {
            switch (txttype.Text.ToLower())
            {
                case "*.js":
                    if (txtdir.Text.ToLower().EndsWith("web\\inc\\css"))
                        txtdir.Text = txtdir.Text.Substring(0, txtdir.TextLength - 7) + "Js";
                    else if (txtdir.Text.ToLower().EndsWith("web\\inc\\css\\"))
                        txtdir.Text = txtdir.Text.Substring(0, txtdir.TextLength - 8) + "Js";
                    break;
                case "*.css":
                    if (txtdir.Text.ToLower().EndsWith("web\\js"))
                        txtdir.Text = txtdir.Text.Substring(0, txtdir.TextLength - 2) + "Inc\\Css";
                    else if (txtdir.Text.ToLower().EndsWith("web\\js\\"))
                        txtdir.Text = txtdir.Text.Substring(0, txtdir.TextLength - 3) + "Inc\\Css";
                    break;
            }
        }

        private void button8_Click(object sender, EventArgs e)
        {
            string str = File.ReadAllText(txtout.Text, Encoding.UTF8);
            str = Regex.Replace(str, @"{(\w+):[^{}]*(((?'O'{)[^{}]*)+((?'-O'})[^{}]*)+)*(?(O)(?!))}", "{\"$1\":");
            //str = Regex.Replace(str, @",(\w+):", ",\"$1\":");
            str = Regex.Replace(str, @"\.(\w+)\(", "[\"$1\"](");
            File.WriteAllText(txtout.Text, str, Encoding.UTF8);
            MessageBox.Show("ok");
            
        }

        private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            System.Diagnostics.Process.Start("explorer", "http://www.javascriptobfuscator.com/");
        }
    }
}
